Ex03 - Histograma e Transformações de intensidade

Esta atividade tem 2 objetivos principais:

- entender o conceito de histograma e estatísticas da imagem
- explorar várias formas de transformação de intensidade dos pixels. 

Parte 1 - Histograma

Leia o notebook Histograma de imagens para entender o conceito de histograma. Além da contagem dos pixels, outras estatísticas podem ser interessantes. Veja abaixo a função h2stats. Ela calcula várias estatísticas da imagem a partir do histograma. Porém, ela foi originalmente desenvolvida para funcionar com a função ia.histogram (antiga toolbox da disciplina).


In [8]:
def h2stats(h):
    import numpy as np
    #import ia898.src as ia

    hn = 1.0*h/h.sum() # compute the normalized image histogram
    v = np.zeros(6) # number of statistics

    # compute statistics
    n = len(h) # number of gray values
    v[0]  = np.sum((np.arange(n)*hn)) # mean
    v[1]  = np.sum(np.power((np.arange(n)-v[0]),2)*hn) # variance
    v[2]  = np.sum(np.power((np.arange(n)-v[0]),3)*hn)/(np.power(v[1],1.5))# skewness
    v[3]  = np.sum(np.power((np.arange(n)-v[0]),4)*hn)/(np.power(v[1],2))-3# kurtosis
    v[4]  = -(hn[hn>0]*np.log(hn[hn>0])).sum() # entropy
    v[5]  = np.argmax(h) # mode
    return v

Vamos agora fazer um teste, calculando o histograma usando a função np.histogram e depois calculando as estatísticas da imagem:


In [9]:
import numpy as np
f = np.array([1,1,1,0,1,2,2,2,1])
h, bins = np.histogram(f)
print('statistics =', h2stats(h))


statistics = [ 5.77777778  7.50617284 -0.51254498 -0.16094616  0.93688831  5.        ]

Os valores calculados parecem corretos? Vejamos o valor da média, por exemplo, usando a função np.mean:


In [10]:
print(np.mean(f))


1.22222222222

Porque os valores de média calculados pela h2stats (5.7777778) e pela np.mean(1.2222222222) são diferentes? Muito provavelmente o problema é a diferença entre a função ia.histogram e np.histogram.

Exercício 1

Pensando que gostaríamos de usar a função h2stats com a função np.histogram, descubram se há uma forma correta de usar a função np.histogram para obter os valores corretos das estatísticas sem alterar a função h2stats. Caso vocês não obtenham sucesso, alterem a função h2stats para que os cálculos fiquem corretos. Testem com arrays numéricos pequenos. Para checar se as estatísticas retornadas estão corretas, usem funções do Numpy e, eventualmente, do Scipy para confirmar (por exemplo: np.mean( ), scipy.stats.skew( )).

Parte 2 - Transformação de Intensidade

É a categoria de funções que apenas alteram o valor do pixel aplicando-se uma função ou tabela de mapeamento. Estudem atentamente os tutoriais sobre Transformada de intensidade e sobre Equalização de histograma. O último tutorial mostra que é possível fazer a equalização da imagem utilizando também o conceito usado para construir um mosaico com tons de cinza igualmente distribuídos.

Exercício 2

Exercite transformações de intensidade em uma imagem.

Exercício 3

Veja a imagem abaixo. Escolha um valor de limiar (threshold) para separar as bolachas do fundo da imagem. Dica: Visualize o histograma da imagem para escolher o valor. Crie primeiro uma função de transformação T e depois aplique esta transformação para obter o objeto de interesse (cookies) pintados de branco e o fundo em preto.


In [11]:
import numpy as np
import matplotlib.image as mpimg
import matplotlib.pyplot as plt

%matplotlib inline
f = mpimg.imread('../figures/cookies.pgm')  
plt.imshow(f,cmap='gray')


Out[11]:
<matplotlib.image.AxesImage at 0x118f36710>

Exercício 4

Você é capaz de transformar a imagem para identificar o número da placa do carro apresentado na imagem abaixo?


In [12]:
f = mpimg.imread('../figures/fusca.png')  
plt.imshow(f,cmap='gray')


Out[12]:
<matplotlib.image.AxesImage at 0x11937aa20>

Exercício 5

Escreva uma função que implemente a tranformação de brilho e contraste de uma imagem em níveis de cinza, baseada na construçao de três segmentos de retas:

  • Primeiro segmento de reta: 'x' de '0' a 'x1', com angulo 'alpha';
  • Segundo segmento de reta: 'x' de 'x1' a 'x2', com angulo 'beta';
  • Terceiro segmento de reta: 'x' de 'x2' a '255';
  • Retorno: mapeamento de brilho & contraste da 'imagem' de entrada.

In [36]:
from PIL import Image
ang = Image.open('../figures/bc_angulos.png')
ang


Out[36]:

Dicas:

  • Determine y1 e y2 a partir de alpha e beta.
  • Utilize a equação da reta, tendo dois pontos conhecidos (xa,ya) e (xb,yb), para cada trecho de reta